package com.orm.mybatisplus.config;
import com.orm.mybatisplus.annotation.DataSource;
import com.orm.mybatisplus.util.DbUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Order(-10)   //加上这个后，会先切面切换数据源再切换事务，可以在方法里叠加    @Transactional @DataSource(value = DbUtil.DB_MASTER1) 这样就会先切换数据源再添加事务，不会导致无法切换数据源
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
@Aspect
@Component
public class AOPAspectAnnotation {

//    private AtomicInteger count = new AtomicInteger(0);  //读写分离


    @Pointcut(value = "@annotation(com.orm.mybatisplus.annotation.DataSource)")  //注意这里是全文件匹配函数
    public void getPoint() {
    }

    @Before("getPoint()")
    public void setPointAcc1(){
        System.out.println("BeforeGetPoint");
    }

    @Around("getPoint()")
    public Object getDoAround(ProceedingJoinPoint pjp){
        ThreadLocal<Long> startTime = new ThreadLocal<>();
        startTime.set(System.currentTimeMillis());
        System.out.println("我是环绕通知执行");
        Object obj;
        try{
            DataSource dataSource = null;
            MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
            Method method = methodSignature.getMethod();
            dataSource =  method.getAnnotation(DataSource.class);
            if (dataSource==null){
                System.out.println("空值");
                System.out.println(DbUtil.DB_MASTER1);
                DatabaseContextHolder.setDBKey(dataSource.value());
                obj = pjp.proceed();
                System.out.println("执行返回值 : " + obj);
            }else {
                System.out.println(dataSource.value());
//                if (dataSource.value().equals(DbUtil.DB_MASTER1)){ //读写分离 start
               DatabaseContextHolder.setDBKey(dataSource.value());
//                }else {                                            //读写分离 middle
//             // 读 简单负载均衡
//             int number = Math.abs(count.getAndAdd(1));
//             int lookupKey = number % 2;
//             if (lookupKey==1){
//                 DatabaseContextHolder.setDBKey(DbUtil.DB_MASTER2);
//             }else{
//                 DatabaseContextHolder.setDBKey(DbUtil.DB_MASTER2);
//             }
//                }
                obj = pjp.proceed();
                System.out.println("执行返回值 : " + obj);
            }
            System.out.println(pjp.getSignature().getName()+"方法执行耗时: " + (System.currentTimeMillis() - startTime.get()));
        } catch (Throwable throwable) {
            System.out.println(throwable+"报错");
            obj=throwable.toString();
        }
        return obj;
    }

    @After("getPoint()")
    public void setPointAcc2(){
        System.out.println("AfterGetPoint");
        DatabaseContextHolder.clearDBKey();
    }

    /**
     * 执行完请求可以做的
     * @param result
     * @throws Throwable
     */
    @AfterReturning(returning = "result", pointcut = "getPoint()")
    public void doAfterReturning(Object result){
        System.out.println("大家好，我是@AfterReturning，他们都秀完了，该我上场了"+result);
    }


}
